package com.zjb.demo.system.service;

import cn.hutool.core.collection.CollectionUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import com.zjb.demo.common.constant.CacheConstants;
import com.zjb.demo.common.util.CastUtils;
import com.zjb.demo.system.domain.SysDictData;
import com.zjb.demo.system.domain.query.SysDictDataQuery;
import com.zjb.demo.system.mapper.SysDictDataMapper;
import org.noear.redisx.plus.RedisBucket;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

import static com.zjb.demo.system.domain.table.SysDictDataTableDef.SYS_DICT_DATA;

/**
 * @author 庄佳彬
 * @since 2023/12/28 09:19
 */
@Component
public class SysDictDataService extends ServiceImpl<SysDictDataMapper, SysDictData> {

    @Inject
    private RedisBucket redisBucket;

    /**
     * 分页查询字典数据
     *
     * @param query 查询条件
     * @return 分页结果
     */
    public Page<SysDictData> pageList(SysDictDataQuery query) {
        var page = new Page<SysDictData>(query.getPageNum(), query.getPageSize());
        return queryChain()
                .select(SYS_DICT_DATA.ALL_COLUMNS)
                .from(SYS_DICT_DATA)
                .where(SYS_DICT_DATA.DICT_TYPE.eq(query.getDictType()))
                .and(SYS_DICT_DATA.DICT_LABEL.like(query.getDictLabel()))
                .and(SYS_DICT_DATA.STATUS.eq(query.getStatus()))
                .orderBy(SYS_DICT_DATA.DICT_SORT.asc())
                .page(page);
    }

    /**
     * 根据指定的查询条件获取字典数据列表
     *
     * @param query 查询条件
     * @return 字典数据列表
     */
    public List<SysDictData> list(SysDictDataQuery query) {
        return queryChain()
                .select(SYS_DICT_DATA.ALL_COLUMNS)
                .from(SYS_DICT_DATA)
                .where(SYS_DICT_DATA.DICT_TYPE.eq(query.getDictType()))
                .and(SYS_DICT_DATA.DICT_LABEL.like(query.getDictLabel()))
                .and(SYS_DICT_DATA.STATUS.eq(query.getStatus()))
                .orderBy(SYS_DICT_DATA.DICT_SORT.asc())
                .list();
    }


    /**
     * 根据字典类型查询字典数据列表
     *
     * @param dictType 字典类型
     * @return 符合条件的字典数据列表
     */
    public List<SysDictData> selectDictDataByType(String dictType) {
        var list = getDictCache(dictType);
        if (CollectionUtil.isNotEmpty(list)) {
            return list;
        }
        list = mapper.selectDictDataByType(dictType);
        if (CollectionUtil.isNotEmpty(list)) {
            setDictCache(dictType, list);
            return list;
        }
        return Collections.emptyList();
    }

    private void setDictCache(String key, List<SysDictData> list) {
        redisBucket.storeAndSerialize(getCacheKey(key), list);
    }

    private List<SysDictData> getDictCache(String key) {
        return CastUtils.cast(redisBucket.getAndDeserialize(getCacheKey(key), List.class));
    }

    private String getCacheKey(String key) {
        return CacheConstants.SYS_DICT_KEY + key;
    }

    /**
     * 插入SysDictData对象到数据库中并缓存
     *
     * @param data 要插入的SysDictData对象
     * @return 插入成功返回true，否则返回false
     */
    public Boolean insertAndCache(SysDictData data) {
        var result = this.save(data);
        if (result) {
            var list = mapper.selectDictDataByType(data.getDictType());
            setDictCache(data.getDictType(), list);
        }
        return result;
    }

    /**
     * 更新指定的SysDictData对象并缓存
     *
     * @param data 需要更新的SysDictData对象
     * @return 更新是否成功
     */
    public Boolean updateAndCache(SysDictData data) {
        var result = this.updateById(data);
        if (result) {
            var list = mapper.selectDictDataByType(data.getDictType());
            setDictCache(data.getDictType(), list);
        }
        return result;
    }

    /**
     * 删除指定的字典代码,并一并删除缓存
     *
     * @param dictCodes 需要删除并缓存的字典代码数组
     */
    public void deleteAndCache(Long[] dictCodes) {
        Stream.of(dictCodes)
                .forEach(dictCode -> getByIdOpt(dictCode)//获取数据
                        .ifPresent(data -> {//存在数据
                            this.removeById(dictCode);//删除
                            var list = mapper.selectDictDataByType(data.getDictType());
                            setDictCache(data.getDictType(), list);//更新缓存
                        }));
    }

}
